package com.momo.demo07_ramAndfile;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;

import com.momo.javabean.Article;
import com.momo.utils.DocumentUtils;
import com.momo.utils.LuceneUtils;

/**
 * @see 内存索引库:数据是临时的、访问速度比文件索引库要快、索引库中的数据不能存放太多、内存索引库和文件索引库能结合在一起
 * @see 两个或者两个以上的索引库的合并:
 * @see 如果是内存索引库，直接调用构造函数进行合并就可以了 内存索引库中。也可以调用addIndexesNoOptimize进行合并
 * @see 如果是文件索引库，调用addIndexesNoOptimize进行合并，该方法可以接受多个索引库
 */
public class RamIndex {
    /**
     * 内存索引库
     */
    @Test
    public void testRAM() throws Exception {
        // 创建了内存索引库
        Directory directory = new RAMDirectory();
        IndexWriter indexWriter = new IndexWriter(directory, LuceneUtils.analyzer, MaxFieldLength.LIMITED);
        Article article = new Article();
        article.setId(26L);
        article.setTitle("NBA总冠军");
        article.setContent("LBJ和韦德能带领热火在2013赛季拿到NBA总冠军吗");
        Document document = DocumentUtils.article2Document(article);
        indexWriter.addDocument(document);
        indexWriter.close();
        this.showData(directory);
    }

    /**
     * 内存索引库和文件索引库的结合
     */
    @Test
    public void testRamIndexAndFileIndex() throws Exception {
        Directory fileDirectory = FSDirectory.open(new File("./indexDir"));// 创建两个索引库
        Directory ramDirectory = new RAMDirectory(fileDirectory);

        // 内存索引
        IndexWriter ramIndexWriter = new IndexWriter(ramDirectory, LuceneUtils.analyzer, MaxFieldLength.LIMITED);// 这个ramIndexWriter是针对内存索引库
        Article article = new Article();
        article.setId(26L);
        article.setTitle("热火赢了总冠军");
        article.setContent("哈哈，热火终于赢了，果然不负众望！！");
        Document document = DocumentUtils.article2Document(article);
        ramIndexWriter.addDocument(document);
        ramIndexWriter.close();

        // 文件索引
        IndexWriter fileIndexWriter = new IndexWriter(fileDirectory, LuceneUtils.analyzer, true, MaxFieldLength.LIMITED);// fileIndexWriter对应的索引库是fileDirectory
        fileIndexWriter.addIndexesNoOptimize(ramDirectory);// 把内存索引库的信息写入到文件索引库addIndexesNoOptimize
        fileIndexWriter.close();

        // 经过两个索引操作后，输出最后的数据
        this.showData(fileDirectory);
    }

    /**
     * 当应用程序启动的时候，直接和内存索引库交互，当程序快结束的时候，把内存索引库中的内容追加到文件索引库中
     */
    @Test
    public void testRamIndexAndFileIndex2() throws Exception {
        // 内存索引
        Directory directory = new RAMDirectory();
        IndexWriter ramIndexWriter = new IndexWriter(directory, LuceneUtils.analyzer, MaxFieldLength.LIMITED);
        Article article = new Article();
        article.setId(27L);
        article.setTitle("热火赢了总冠军");
        article.setContent("哈哈，热火终于赢了，果然不负众望！！");
        Document document = DocumentUtils.article2Document(article);
        ramIndexWriter.addDocument(document);
        ramIndexWriter.close();

        // 文件索引
        Directory fileDirectory = FSDirectory.open(new File("./indexDir"));
        IndexWriter fileIndexWriter = new IndexWriter(fileDirectory, LuceneUtils.analyzer, MaxFieldLength.LIMITED);
        fileIndexWriter.addIndexesNoOptimize(directory);
        fileIndexWriter.close();

        // 经过两个索引操作后，输出最后的数据
        this.showData(fileDirectory);
    }

    // 公共输出类
    private void showData(Directory directory) throws Exception {
        IndexSearcher indexSearcher = new IndexSearcher(directory);
        QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_30, new String[]{"title", "content"}, LuceneUtils.analyzer);
        Query query = queryParser.parse("总冠军");
        TopDocs topDocs = indexSearcher.search(query, 50);
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        List<Article> articleList = new ArrayList<Article>();
        for (int i = 0; i < scoreDocs.length; i++) {
            Document document = indexSearcher.doc(scoreDocs[i].doc);
            Article article = DocumentUtils.document2Article(document);
            articleList.add(article);
        }

        // 输出查询出来的索引对象
        for (Article article : articleList) {
            System.out.println(article.getId());
            System.out.println(article.getTitle());
            System.out.println(article.getContent());
        }
    }
}
